/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.farent.solutions.plugins.stripes.hyperstripes.ext;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

/**
 *
 * @author user
 */
public class WebXMLParser {

    private org.w3c.dom.Document document;

    /**
     * This constructor method is passed an XML file. It uses the JAXP API to
     * obtain a DOM parser, and to parse the file into a DOM Document object,
     * which is used by the remaining methods of the class.
     */
    public WebXMLParser(InputStream configfile) throws IOException, SAXException,
            ParserConfigurationException {
        javax.xml.parsers.DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setValidating(false);
        javax.xml.parsers.DocumentBuilder parser = dbf.newDocumentBuilder();

        parser.setErrorHandler(new org.xml.sax.ErrorHandler() {

            @Override
            public void warning(SAXParseException e) {
                System.err.println("WARNING: " + e.getMessage());
            }

            @Override
            public void error(SAXParseException e) {
                System.err.println("ERROR: " + e.getMessage());
            }

            @Override
            public void fatalError(SAXParseException e) throws SAXException {
                System.err.println("FATAL: " + e.getMessage());
                throw e; // re-throw the error
            }
        });

        document = parser.parse(configfile);
    }

    /**
     * This method looks for specific Element nodes in the DOM tree in order to
     * figure out the classname associated with the specified servlet name
     */
    public String getServletClassForName(String servletName) {
        NodeList servletnodes = document.getElementsByTagName("servlet");
        int numservlets = servletnodes.getLength();
        for (int i = 0; i < numservlets; i++) {
            Element servletTag = (Element) servletnodes.item(i);
            Element nameTag = (Element) servletTag.getElementsByTagName("servlet-name").item(0);
            if (nameTag == null) {
                continue;
            }

            String name = ((Text) nameTag.getFirstChild()).getData().trim();

            // If this <servlet-name> tag has the right name
            if (servletName.equals(name)) {
                // Get the matching <servlet-class> tag
                Element classTag = (Element) servletTag.getElementsByTagName("servlet-class").item(0);
                if (classTag != null) {
                    // Extract the tag's text as above, and return it
                    Text classTagContent = (Text) classTag.getFirstChild();
                    return classTagContent.getNodeValue().trim();
                }
            }
        }
        // If we get here, no matching servlet name was found
        return null;
    }

    /**
     * This method looks for specific Element nodes in the DOM tree in order to
     * figure out the servletName associated with the specified servletClass
     */
    public String getServletNameForClass(String servletClass) {
        NodeList servletnodes = document.getElementsByTagName("servlet");
        int numservlets = servletnodes.getLength();
        for (int i = 0; i < numservlets; i++) {
            Element servletTag = (Element) servletnodes.item(i);
            Element nameTag = (Element) servletTag.getElementsByTagName("servlet-class").item(0);
            if (nameTag == null) {
                continue;
            }

            String className = ((Text) nameTag.getFirstChild()).getData().trim();

            // If this <servlet-name> tag has the right name
            if (servletClass.equals(className)) {
                // Get the matching <servlet-class> tag
                Element classTag = (Element) servletTag.getElementsByTagName("servlet-name").item(0);
                if (classTag != null) {
                    // Extract the tag's text as above, and return it
                    Text classTagContent = (Text) classTag.getFirstChild();
                    return classTagContent.getNodeValue().trim();
                }
            }
        }
        // If we get here, no matching servlet name was found
        return null;
    }

    /**
     * This method looks for specific Element nodes in the DOM tree in order to
     * figure out the servletName associated with the specified servletClass
     */
    public String getServletPathForClass(String servletClass) {
        NodeList servletnodes = document.getElementsByTagName("servlet");
        int numservlets = servletnodes.getLength();
        for (int i = 0; i < numservlets; i++) {
            Element servletTag = (Element) servletnodes.item(i);
            Element nameTag = (Element) servletTag.getElementsByTagName("servlet-class").item(0);
            if (nameTag == null) {
                continue;
            }
            String className = ((Text) nameTag.getFirstChild()).getData().trim();
            String servletName = null;
            if (servletClass.equals(className)) {
                Element classTag = (Element) servletTag.getElementsByTagName("servlet-name").item(0);
                if (classTag != null) {
                    // Extract the tag's text as above, and return it
                    Text classTagContent = (Text) classTag.getFirstChild();
                    servletName =  classTagContent.getNodeValue().trim();
                }
                if( servletName!= null && !servletName.isEmpty() )
                    return getFirstServletURLPatternForName(servletName);
            }
        }
        // If we get here, no matching servlet name was found
        return null;
    }

    /**
     * This method looks for specific Element nodes in the DOM tree in order to
     * figure out the servletName associated with the specified servletClass
     */
    public String getFirstServletURLPatternForName(String servletName) {
        NodeList servletMappings = document.getElementsByTagName("servlet-mapping");
        int numservlets = servletMappings.getLength();
        for (int i = 0; i < numservlets; i++) {
            Element servletTag = (Element) servletMappings.item(i);
            Element nameTag = (Element) servletTag.getElementsByTagName("servlet-name").item(0);
            if (nameTag == null) {
                continue;
            }

            String currentName = ((Text) nameTag.getFirstChild()).getData().trim();

            // If this <servlet-name> tag has the right name
            if (servletName.equals(currentName)) {
                // Get the matching <servlet-class> tag
                Element classTag = (Element) servletTag.getElementsByTagName("url-pattern").item(0);
                if (classTag != null) {
                    // Extract the tag's text as above, and return it
                    Text classTagContent = (Text) classTag.getFirstChild();
                    return classTagContent.getNodeValue().trim();
                }
            }
        }
        // If we get here, no matching servlet name was found
        return null;
    }

    /**
     * This method looks for specific Element nodes in the DOM tree in order to
     * figure out the servletName associated with the specified servletClass
     */
    public List<String> getServletURLPatternsForName(String servletName) {
        List<String> urls = new ArrayList<String>();
        NodeList servletMappings = document.getElementsByTagName("servlet-mapping");
        int numservlets = servletMappings.getLength();
        for (int i = 0; i < numservlets; i++) {
            Element servletTag = (Element) servletMappings.item(i);
            Element nameTag = (Element) servletTag.getElementsByTagName("servlet-name").item(0);
            if (nameTag == null) {
                continue;
            }

            String currentName = ((Text) nameTag.getFirstChild()).getData().trim();

            // If this <servlet-name> tag has the right name
            if (servletName.equals(currentName)) {
                // Get the matching <servlet-class> tag
                Element classTag = (Element) servletTag.getElementsByTagName("url-pattern").item(0);
                if (classTag != null) {
                    // Extract the tag's text as above, and return it
                    Text classTagContent = (Text) classTag.getFirstChild();
                    String url =  classTagContent.getNodeValue().trim();
                    urls.add(url);
                }
            }
        }
        return urls;
    }

    /**
     * This method looks for specific Element nodes in the DOM tree in order to
     * figure out the servletName associated with the specified servletClass
     */
    public List<ServletInfo> getAllServlets() {

        List<ServletInfo> infos = new ArrayList<ServletInfo>();
        NodeList servletnodes = document.getElementsByTagName("servlet");
        int numservlets = servletnodes.getLength();
        for (int i = 0; i < numservlets; i++) {
            Element servletTag = (Element) servletnodes.item(i);
            Element nameTag = (Element) servletTag.getElementsByTagName("servlet-class").item(0);
            if (nameTag == null) {
                continue;
            }
            String className = ((Text) nameTag.getFirstChild()).getData().trim();
            String servletName = null;

            Element classTag = (Element) servletTag.getElementsByTagName("servlet-name").item(0);
            if (classTag != null) {
                Text classTagContent = (Text) classTag.getFirstChild();
                servletName =  classTagContent.getNodeValue().trim();
            }

            List<String> servletUrls = getServletURLPatternsForName(servletName);
            ServletInfo info = new ServletInfo(className, servletName, servletUrls);
            infos.add(info);
        }
        // If we get here, no matching servlet name was found
        return infos;
    }
}
